package com.cetcs.kmga.dataManager.service.impl.sysManager;

import com.cetcs.kmga.common.Data;
import com.cetcs.kmga.dataManager.dao.mybatis.AuditManagerMapper;
import com.cetcs.kmga.dataManager.dao.mybatis.ClientDBMapper;
import com.cetcs.kmga.dataManager.dao.mybatis.FeatureCodeMapper;
import com.cetcs.kmga.dataManager.entity.dataManager.ClientDB;
import com.cetcs.kmga.dataManager.entity.dataManager.ClientDBCluster;
import com.cetcs.kmga.dataManager.entity.dataManager.ClientDBClusterAndClient;
import com.cetcs.kmga.dataManager.entity.dataManager.Resrc;
import com.cetcs.kmga.dataManager.entity.dataManager.vo.ResourceTreeDataBaseVo;
import com.cetcs.kmga.dataManager.entity.dataManager.vo.ResourceTreeDataObjectVo;
import com.cetcs.kmga.dataManager.entity.dataManager.vo.ResourceTreeDataTableVo;
import com.cetcs.kmga.dataManager.entity.global.AlarmCode;
import com.cetcs.kmga.dataManager.schedule.InitCdTypeListener;
import com.cetcs.kmga.dataManager.service.sysManager.ClientDBService;
import com.cetcs.kmga.dataManager.util.CommonUtils;
import com.cetcs.kmga.dataManager.util.ExcelUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.xssf.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;


/**
 * Created by yyangs on 2017/2/14.
 */
@Service
public class ClientDBServiceImpl implements ClientDBService {
    @Autowired
    private InitCdTypeListener initCdTypeListener;
    @Autowired
    private ClientDBMapper clientDBMapper;
    @Autowired
    private FeatureCodeMapper featureCodeMapper;
    @Autowired
    private AuditManagerMapper auditManagerMapper;

    private static Log LOGGER = LogFactory.getLog(ClientDBServiceImpl.class);


    /**
     * 获得客户端类型配置 集群列表
     * @param dataMap
     * @return
     * @throws Exception
     */
    @Override
    public List<ResourceTreeDataBaseVo> getClientNodeTree(Data dataMap) throws Exception {
        //第一步 先按照码表将四个类型的列表 创建
        //获取客户端类型
        List<AlarmCode> alarmCodes = featureCodeMapper.findFeatureCodesByTypeId(21);
        //第二步 将数据库中的集群数据和那个 客户端数据查询出来
        //查询所有的集群和客户端数据
        List<ClientDBClusterAndClient> clientDBClusterAndClients = clientDBMapper.getClientNodeTree(dataMap);
        //第三步 将查出来的列表分组 根据 类型
        //分组 更具类型
        Map<String, List<ClientDBClusterAndClient>> map = new LinkedHashMap<String, List<ClientDBClusterAndClient>>();
        CommonUtils.listGroup2Map(clientDBClusterAndClients, map, ClientDBClusterAndClient.class, "getType");// 输入方法名
        //第四步 每一个分组里面的数据 在进行分组
        List<ResourceTreeDataBaseVo> resourceTreeDataBaseVos = Lists.newArrayList();
        for(AlarmCode alarmCode:alarmCodes){
            //循环遍历每一种类型
            ResourceTreeDataBaseVo resourceTreeDataBaseVo = new ResourceTreeDataBaseVo();
            resourceTreeDataBaseVo.setId("A"+alarmCode.getCode());
            resourceTreeDataBaseVo.setName(alarmCode.getValue());
            List<ResourceTreeDataTableVo> item = Lists.newArrayList();
            if(map.get(alarmCode.getCode())!=null){
                //数据中有这个类型的数据 填充进去
                List<ClientDBClusterAndClient> clientDBClusterAndClientList = map.get(alarmCode.getCode());
                Map<String, List<ClientDBClusterAndClient>> mapObject = new LinkedHashMap<String, List<ClientDBClusterAndClient>>();
                CommonUtils.listGroup2Map(clientDBClusterAndClientList, mapObject, ClientDBClusterAndClient.class, "getId");// 输入方法名
                //在分组
                for(Map.Entry<String,List<ClientDBClusterAndClient>> entry:mapObject.entrySet()){
                    ResourceTreeDataTableVo resourceTreeDataTableVo = new ResourceTreeDataTableVo();
                    resourceTreeDataTableVo.setId("B"+entry.getKey());
                    resourceTreeDataTableVo.setTable(entry.getValue().get(0).getName());
                    List<ResourceTreeDataObjectVo> child = Lists.newArrayList();
                    //循环遍历 将数据取出
                    for(ClientDBClusterAndClient clientDBClusterAndClient:entry.getValue()){
                        if(clientDBClusterAndClient.getIp()!=null) {
                            ResourceTreeDataObjectVo resourceTreeDataObjectVo = new ResourceTreeDataObjectVo();
                            //resourceTreeDataObjectVo.setId("C"+clientDBClusterAndClient.getIp().replace(".","_"));
                            resourceTreeDataObjectVo.setId("C" + clientDBClusterAndClient.getIp());
                            resourceTreeDataObjectVo.setName(clientDBClusterAndClient.getIp());
                            child.add(resourceTreeDataObjectVo);
                        }
                    }
                    resourceTreeDataTableVo.setChild(child);
                    item.add(resourceTreeDataTableVo);
                }
            }
            resourceTreeDataBaseVo.setItem(item);
            resourceTreeDataBaseVos.add(resourceTreeDataBaseVo);
        }
        return resourceTreeDataBaseVos;
    }

    /**
     * 获得客户端集群信息  通过ID
     * @param dataMap
     * @return
     * @throws Exception
     */
    @Override
    public ClientDBCluster getClientClusterById(Data dataMap) throws Exception {
        List<ClientDBCluster> clientDBClusters = clientDBMapper.getClientClusterByCondition(dataMap);
        if(clientDBClusters.size()>0){
            return clientDBClusters.get(0);
        }else{
            return null;
        }
    }

    /**
     * 跟新客户端集群信息
     * @param dataMap
     * @return
     * @throws Exception
     */
    @Override
    public Integer updateClientCluster(Data dataMap) throws Exception {
        Data params = new Data();
        params.put("idF",dataMap.get("id"));
        params.put("name",dataMap.get("name"));
        List<ClientDBCluster> clientDBClusters = clientDBMapper.getClientClusterByCondition(params);
        if(clientDBClusters.size()>0){
            return 0;
        }else {
            //先检查名称是否重复
            Integer result = clientDBMapper.updateClientCluster(dataMap);
            if(result>0){
                initCdTypeListener.reloadSysClenitCodeTb();
            }
            return result;
        }
    }

    /**
     * 添加客户端集群信息
     * @param dataMap
     * @return
     * @throws Exception
     */
    @Override
    public Integer addClientCluster(Data dataMap) throws Exception {
        Data params = new Data();
        params.put("name",dataMap.get("name"));
        List<ClientDBCluster> clientDBClusters = clientDBMapper.getClientClusterByCondition(params);
        if(clientDBClusters.size()>0){
            return 0;
        }else {
            //先检查名称是否重复
            Integer result = clientDBMapper.addClientCluster(dataMap);
            if(result>0){
                initCdTypeListener.reloadSysClenitCodeTb();
            }
            return result;
        }
    }

    /**
     * 添加或者修改 客户端信息
     * @param dataMap
     * @return
     * @throws Exception
     */
    @Override
    public Integer saveOrUpdateClient(Data dataMap) throws Exception {
        //判断该IP是否已经在其他的集群下面，如果不是 则直接replace语句
        Data params = new Data();
        params.put("ip",dataMap.get("ip"));
        //表示不为当前集群下的 同时 不能为null
        params.put("cluster_idF",dataMap.get("cluster_id"));
        params.put("cluster_id_not_null",1);
        List<ClientDB> clientDBS = clientDBMapper.getClientDBByCondition(params);
        if(clientDBS.size()>0){
            return 0;
        }else{
            //说明不存在其他集群下的
            dataMap.put("deal_flag",1);
            dataMap.put("create_time",new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            Integer result = 0;
            result = clientDBMapper.saveOrUpdateClient(dataMap);
            if(result>0){
                initCdTypeListener.reloadSysClenitCodeTb();
            }
            return result;
        }
    }


    /**
     * 删除客户端信息
     * @param dataMap
     * @return
     * @throws Exception
     */
    @Override
    public Integer deleteClient(Data dataMap) throws Exception {
        //通过IP将数据删除
        return  clientDBMapper.deleteClient(dataMap);
    }


    /**
     * 删除客户端集群信息
     * @param dataMap
     * @return
     * @throws Exception
     */
    @Override
    public Integer deleteClientCluster(Data dataMap) throws Exception {
        //先删除客户端集群
        Integer result = clientDBMapper.deleteClientCluster(dataMap);
        if(result>0) {
            Data params = new Data();
            params.put("cluster_id", dataMap.get("id"));
            //然后删除该集群下的客户端
            result += clientDBMapper.deleteClient(params);
        }
        initCdTypeListener.reloadSysClenitCodeTb();
        return result;
    }




    /**
     * 导出客户端数据 excel
     * @param dataMap
     * @return
     */
    @Override
    public String exportExcelForClientData(Data dataMap) throws Exception {
        //先将所有需要的数据取出来 包括 类型列表 资源列表 客户端数据
        //获取客户端集群类型
        List<AlarmCode> alarmCodes = featureCodeMapper.findFeatureCodesByTypeId(21);
        Map<String,String> mapType = Maps.newHashMap();
        List<String> typeString = Lists.newArrayList();
        alarmCodes.forEach(p->{
            mapType.put(p.getCode(),p.getValue());
            typeString.add(p.getValue());
        });
        String[] strType=new String[typeString.size()];
        strType= typeString.toArray(strType);
        //获取资源列表
        List<Resrc> resrcList = auditManagerMapper.getAllResrcByCondition(dataMap);
        Map<String,String> mapResource = Maps.newHashMap();
        List<String> resourceString = Lists.newArrayList();
        resrcList.forEach(p->{
            mapResource.put(String.valueOf(p.getId()),p.getName());
            resourceString.add(p.getName());
        });
        String[] strResource=new String[resourceString.size()];
        strResource= resourceString.toArray(strResource);
        //查询所有的集群和客户端数据
        List<ClientDBClusterAndClient> clientDBClusterAndClients = clientDBMapper.getClientNodeTree(dataMap);

        List<String> head = Lists.newArrayList("客户端IP", "所属客户端集群名称", "集群类型", "数据采集集群");

        //==============导出Excel============

        Integer rowNum = 0;

        XSSFWorkbook workBook = new XSSFWorkbook();
        XSSFSheet sheet = workBook.createSheet("Sheet1");
        sheet.setColumnWidth(0, 20 * 256);
        sheet.setColumnWidth(1, 20 * 256);
        sheet.setColumnWidth(2, 20 * 256);
        sheet.setColumnWidth(3, 20 * 256);
        ExcelUtil exportUtil = new ExcelUtil(workBook, sheet);
        XSSFCellStyle headStyle = exportUtil.getHeadStyle();
        XSSFCellStyle bodyStyle = exportUtil.getBodyStyle();
        XSSFCell cell = null;

        // 构建表头
        XSSFRow headRow = sheet.createRow(rowNum++);
        headRow.setHeightInPoints(20);
        int i = 0;
        for (String s : head) {
            cell = headRow.createCell(i++);
            cell.setCellStyle(headStyle);
            cell.setCellValue(s.trim());
            if("集群类型".equals(s)) {
                //设置单元格格式
                XSSFDataValidationHelper dvHelper = new XSSFDataValidationHelper((XSSFSheet)sheet);
                XSSFDataValidationConstraint dvConstraint = (XSSFDataValidationConstraint) dvHelper
                        .createExplicitListConstraint(strType);
                CellRangeAddressList addressList = new CellRangeAddressList(0, 65536, 2, 2);
                XSSFDataValidation validation = (XSSFDataValidation) dvHelper.createValidation(dvConstraint, addressList);
                validation.setSuppressDropDownArrow(true);
                sheet.addValidationData(validation);

            }else if("数据采集集群".equals(s)) {
                //设置单元格格式
                XSSFDataValidationHelper dvHelper = new XSSFDataValidationHelper((XSSFSheet)sheet);
                XSSFDataValidationConstraint dvConstraint = (XSSFDataValidationConstraint) dvHelper
                        .createExplicitListConstraint(strResource);
                CellRangeAddressList addressList = new CellRangeAddressList(0, 65536, 3, 3);
                XSSFDataValidation validation = (XSSFDataValidation) dvHelper.createValidation(dvConstraint, addressList);
                validation.setSuppressDropDownArrow(true);
                sheet.addValidationData(validation);

            }
        }


        //添加数据
        for (ClientDBClusterAndClient clientDBClusterAndClient : clientDBClusterAndClients) {
            if("0".equals(clientDBClusterAndClient.getType())){
                continue;
            }
            headRow = sheet.createRow(rowNum++);
            headRow.setHeightInPoints(20);
            i = 0;
            if(clientDBClusterAndClient.getIp()!=null) {
                //客户端IP
                cell = headRow.createCell(i++);
                cell.setCellStyle(bodyStyle);
                cell.setCellValue(clientDBClusterAndClient.getIp().trim());
            }
            if(clientDBClusterAndClient.getName()!=null) {
                //所属客户端集群名称
                cell = headRow.createCell(i++);
                cell.setCellStyle(bodyStyle);
                cell.setCellValue(clientDBClusterAndClient.getName().trim());
            }
            if(clientDBClusterAndClient.getType()!=null) {
                //集群类型
                cell = headRow.createCell(i++);
                cell.setCellStyle(bodyStyle);
                cell.setCellValue(mapType.get(clientDBClusterAndClient.getType()));
            }
            if(clientDBClusterAndClient.getResrc_id()!=null) {
                //数据采集集群
                cell = headRow.createCell(i++);
                cell.setCellStyle(bodyStyle);
                cell.setCellValue(mapResource.get(clientDBClusterAndClient.getResrc_id()));
            }else{
                cell = headRow.createCell(i++);
                cell.setCellStyle(bodyStyle);
                cell.setCellValue("");
            }
        }


        File file = new File(this.getClass().getResource("/").toURI().getPath() + File.separator + "modal");
        if (!file.exists()) file.mkdirs();
        String filePath = file + File.separator + dataMap.get("fileName");
        try {
            FileOutputStream out = new FileOutputStream(filePath);
            workBook.write(out);
            out.flush();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        //然后创建excel
        return filePath;
    }


    /**
     * 解析Excel文档 批量上传IP配置
     * @param dataMap
     * @return
     * @throws Exception
     */
    @Override
    public Integer importExcelForClientData(Data dataMap) throws Exception {
        //循环遍历 每一行的数据
        //如果这一行的数据存在 则报错 同时将标志位 置为Fasle 记录该行的数据 和行数
        //如果false则抛出异常
        //否则 返回成功
        //获取两个码表的数据
        List<AlarmCode> alarmCodes = featureCodeMapper.findFeatureCodesByTypeId(21);
        Map<String,String> mapType = Maps.newHashMap();
        Map<String,String> mapTypeTemp = Maps.newHashMap();
        alarmCodes.forEach(p->{
            mapType.put(p.getValue(),p.getCode());
            mapTypeTemp.put(p.getCode(),p.getValue());
        });
        //获取资源列表
        List<Resrc> resrcList = auditManagerMapper.getAllResrcByCondition(dataMap);
        Map<String,String> mapResource = Maps.newHashMap();
        Map<String,String> mapResourceTemp = Maps.newHashMap();
        resrcList.forEach(p->{
            mapResource.put(p.getName(),String.valueOf(p.getId()));
            mapResourceTemp.put(String.valueOf(p.getId()),p.getName());
        });

        Boolean isSuccess = true;
        List<String> message = Lists.newArrayList();
        //完整路径
        List<String> head = (List<String>) dataMap.get("head");
        List<List<String>> data = (List<List<String>>) dataMap.get("data");
        for(int i=1;i<data.size();i++){
            List<String> obj = data.get(i);
            //先判断该IP是否存在
            Data params = new Data();
            params.put("ip",obj.get(0));
            List<ClientDB> clientDBS = clientDBMapper.getClientDBByCondition(params);
            if(clientDBS.size()>0){
                //存在 将标志位 置为 false 记录错误原因
                isSuccess = false;
                String s = "第" + i + "行 IP:" + obj.get(0) + " 已存在，请去监管平台修改该IP信息。";
                message.add(s);
                LOGGER.info(s);
                continue;
            }else{
                //不存在 添加进去
                //先将集群添加进去 saveOrUpdate 拿到ID 写入后面的数据
                params.clear();
                params.put("name",obj.get(1));
                if(mapType.get(obj.get(2))!=null) {
                    params.put("type", mapType.get(obj.get(2)));
                }
                if("FTP".equals(obj.get(2))){
                    if(mapResource.get(obj.get(3))!=null) {
                        params.put("resrc_id", mapResource.get(obj.get(3)));
                    }
                }
                /**
                 * 先判断是否存在名称相同的 集群
                 */
                List<ClientDBCluster> clientDBClusterLists = clientDBMapper.getClientClusterByCondition(params);
                String id ;
                if(clientDBClusterLists.size()>0){
                    id = clientDBClusterLists.get(0).getId();
                    //存在相同的名称的集群
                    //判断 类型是否相同  ftp还需要判断关联资源
                    if(!params.get("type").equals(clientDBClusterLists.get(0).getType().toString())){
                        //不相同 还需要把标志位置为 false  然后写入错误列表
                        isSuccess = false;
                        String s ;
                        if(clientDBClusterLists.get(0).getType()!="0") {
                            s = "第" + i + "行：IP:" + obj.get(0) + " 所对应的集群" + mapType.get(obj.get(2)) + "的类型（" + obj.get(2) + "）与数据库中(" + mapTypeTemp.get(clientDBClusterLists.get(0).getType()) + ")不匹配，请核对信息";
                        }else{
                            s = "第" + i + "行：IP:" + obj.get(0) + " 所对应的集群" + mapType.get(obj.get(2)) + "的类型（" + obj.get(2) + "）与数据库中不匹配，请核对信息";
                        }
                        message.add(s);
                        continue;
                    }else{
                        if("FTP".equals(obj.get(2))) {
                            if(!params.get("resrc_id").equals(clientDBClusterLists.get(0).getResrc_id().toString())) {
                                //对应的资源 不相同
                                //不相同 还需要把标志位置为 false  然后写入错误列表
                                isSuccess = false;
                                String s = "第" + i +"行：IP:" + obj.get(0) + " 所对应的集群" + mapType.get(obj.get(2)) + "的所属资源类型（" + obj.get(3) + "）与数据库中(" + mapResourceTemp.get(clientDBClusterLists.get(0).getResrc_id()) + ")不匹配，请核对信息";
                                LOGGER.info(s);
                                message.add(s);
                                continue;
                            }
                        }
                    }
                }else{
                    clientDBMapper.addClientCluster(params);
                    id = params.getString("id");
                }
                params.clear();
                params.put("ip",obj.get(0));
                params.put("cluster_id",id);
                params.put("name",obj.get(0));
                params.put("type_code",1);
                params.put("create_time",new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                params.put("deal_flag",1);
                clientDBMapper.saveOrUpdateClient(params);
                LOGGER.info("IP:"+obj.get(0) + "插入数据库成功");
            }
            //进行下次循环
        }

        if(!isSuccess){
            throw new Exception("Execl数据出错" + message.toString());
        }
        initCdTypeListener.reloadSysClenitCodeTb();
        return 1;
    }

}
